﻿// 功能：用来将Winform UI 中控件嵌入MzFC窗口或控件中
// 描述：
// 作者：温伟鹏
// 日期：2010/6/3 11:38:47

using System;
using System.Runtime.InteropServices;
using System.Drawing;

namespace MeizuSDK.Presentation.Integration
{
    /// <summary>
    /// 用来将WinformUI中控件嵌入MzFC UiElement的控件
    /// </summary>
    public class ControlHost : Control
    {
        #region DllImport

        [DllImport("MZFCWrapper.dll")]
        private static extern IntPtr UiWinCtor();

        #endregion

        #region 事件
        /// <summary>
        /// 当Child属性被修改后触发此事件
        /// </summary>
        public event ChildChangedEventHandler ChildChanged;
        #endregion

        #region 私有变量
        /// <summary>
        /// WinForm 控件
        /// </summary>
        private System.Windows.Forms.Control child;
        /// <summary>
        /// Winform控件容器
        /// </summary>
        private System.Windows.Forms.Panel hostContainer;
        #endregion

        #region 公共属性
        /// <summary>
        /// 获取或设置
        /// </summary>
        public System.Windows.Forms.Control Child
        {
            get
            {
                return this.child;
            }
            set
            {
                if (value != this.child)
                {
                    System.Windows.Forms.Control prevChild = this.child;

                    this.child = value;

                    OnChildChanged(new ChildChangedEventArgs(prevChild));
                }
            }
        }
        #endregion

        #region 构造函数
        /// <summary>
        /// 构建ControlHost对象
        /// </summary>
        public ControlHost()
        {
            Handle = UiWinCtor();
            SetID();
            hostContainer = new System.Windows.Forms.Panel();
            hostContainer.BackColor = Color.Yellow;
        }
        #endregion

        #region 函数
        /// <summary>
        /// 重置WinForm子控件
        /// </summary>
        private void ResetChild()
        {
            this.hostContainer.Controls.Clear();

            if (this.child == null)
            {
                this.hostContainer.Hide();
                return;
            }

            switch (this.child.Dock)
            {
                case System.Windows.Forms.DockStyle.Fill:
                    {
                        this.hostContainer.Location = new Point(X, Y);
                        this.hostContainer.Size = new Size(Width, Height);
                        this.child.Location = new Point(0, 0);
                        this.child.Size = new Size(ContentWidth, ContentHeight);
                    }
                    break;
                case System.Windows.Forms.DockStyle.Bottom:
                    {
                        this.child.Location = new Point(0, ContentHeight);
                        this.child.Size = new Size(ContentWidth, Math.Min(ContentHeight, this.child.Height));

                        this.hostContainer.Location = new Point(X, Y + (Height - this.child.Height));
                        this.hostContainer.Size = new Size(Width, Math.Min(Height, this.child.Height + 1));
                    }
                    break;
                case System.Windows.Forms.DockStyle.Left:
                    {
                        this.child.Location = new Point(0, 0);
                        this.child.Size = new Size(Math.Min(ContentWidth, this.child.Width), ContentHeight);

                        this.hostContainer.Location = new Point(X, Y);
                        this.hostContainer.Size = new Size(Math.Min(Width, this.child.Width + 1), Height);
                    }
                    break;
                case System.Windows.Forms.DockStyle.Right:
                    {
                        this.child.Location = new Point(0, 0);
                        this.child.Size = new Size(Math.Min(ContentWidth, this.child.Width), ContentHeight);

                        this.hostContainer.Location = new Point(Width - this.child.Width - 1, Y);
                        this.hostContainer.Size = new Size(Math.Min(Width, this.child.Width + 1), Height);
                    }
                    break;
                case System.Windows.Forms.DockStyle.Top:
                    {
                        this.child.Location = new Point(0, 0);
                        this.child.Size = new Size(ContentWidth, Math.Min(ContentHeight, this.child.Height));

                        this.hostContainer.Location = new Point(X, Y);
                        this.hostContainer.Size = new Size(Width, Math.Min(Height, this.child.Height + 1));
                    }
                    break;
                default:
                    {
                        this.child.Location = new Point(0, 0);
                        this.child.Size = new Size(Math.Min(ContentWidth, this.child.Width), Math.Min(this.child.Height, ContentHeight));

                        this.hostContainer.Location = new Point(X, Y);
                        this.hostContainer.Size = new Size(Math.Min(Width, this.child.Width + 1), Math.Min(Height, this.child.Height + 1));
                    }
                    break;
            }

            this.hostContainer.Controls.Add(this.child);

            // 显示控件
            if (OwnerForm != null && OwnerForm.IsHandleCreated && this.hostContainer.Handle != IntPtr.Zero)
            {
                NativeMethods.SetParent(this.hostContainer.Handle, OwnerForm.HWnd);
                NativeMethods.SetWindowPos(this.hostContainer.Handle, new IntPtr(0), this.hostContainer.Location, this.hostContainer.Size);
                this.hostContainer.Show();
            }
        }
        /// <summary>
        /// 引发 ParentChanged 事件
        /// </summary>
        /// <param name="e"></param>
        protected override void OnParentChanged(ParentChangedEventArgs e)
        {
            ResetChild();

            base.OnParentChanged(e);
        }
        /// <summary>
        /// 引发 LocationChanged 事件
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLocationChanged(EventArgs e)
        {
            ResetChild();

            base.OnLocationChanged(e);
        }
        /// <summary>
        /// 引发 SizeChanged 事件
        /// </summary>
        /// <param name="e"></param>
        protected override void OnSizeChanged(EventArgs e)
        {
            ResetChild();

            base.OnSizeChanged(e);
        }
        /// <summary>
        /// 引发 ChildChanged 事件
        /// </summary>
        /// <param name="e">事件参数</param>
        protected virtual void OnChildChanged(ChildChangedEventArgs e)
        {
            if (ChildChanged != null)
            {
                ChildChanged(this, e);
            }
        }
        /// <summary>
        /// 销毁资源
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            try
            {
                if (Child != null)
                {
                    Child.Dispose();
                }

                base.Dispose(disposing);
            }
            catch (Exception) { }
        }
        #endregion
    }
}
